extends BTAction

##region 配置参数
var _path_update_threshold := 5.0 # 路径更新距离阈值（单位：像素）
var _collision_check_timer := 10.0 # 绕行检测间隔计时器（单位：秒）
var ally_collision_mask := 1 # 友军碰撞层掩码
var enemy_collision_mask := 2 # 敌军碰撞层掩码
##endregion
var _avoid_distance := 12.0 # 检测三角形边长
var _avoid_angle := deg_to_rad(60) # 检测角度
var _avoid_speed_ratio := 1 # 侧移速度比例

var _cached_shape := ConvexPolygonShape2D.new() # 添加持久化形状实例
var _last_dir := Vector2(1, 1) # 记录上次方向用于检测更新需求
##region 行为树回调
func _enter() -> void:
	var unit = agent as Unit
	var target = unit.current_target
	
	# 双保险有效性验证（Godot推荐的内存安全校验模式）
	if not (is_instance_valid(unit) or is_instance_valid(target)):
		return
	
	unit.nav_agent.avoidance_priority = 0.01
	unit.nav_agent.max_speed = unit.speed

func _tick(delta: float) -> Status:
	var unit = agent as Unit
	var target = unit.current_target
	if not is_instance_valid(target):
		return Status.FAILURE

	_update_target_position(unit, target)
	_handle_collision_check_timer(delta, unit)
	
	var next_pos = unit.nav_agent.get_next_path_position()
	var base_dir = (next_pos - unit.global_position).normalized()
	
	var desired_velocity = _calculate_base_velocity(unit, base_dir)
	desired_velocity = _apply_avoidance(unit, base_dir, desired_velocity)
	
	unit.nav_agent.set_velocity(desired_velocity)
	unit.move_and_slide()
	# 根据剩余距离返回状态（8像素阈值范围）
	return Status.RUNNING if unit.global_position.distance_to(unit.current_target.global_position) > unit.min_attack_range + 8 else Status.SUCCESS
	##endregion
##endregion


##region 路径更新
func _update_target_position(unit: Unit, target: Unit):
	# 计算理想站位点（保持最小攻击距离）
	var to_unit_dir = (unit.global_position - target.global_position).normalized()
	var desired_pos = target.global_position + to_unit_dir * (unit.min_attack_range)
	var current_distance = unit.global_position.distance_to(desired_pos)

	# 路径更新触发条件（满足任意条件即更新）
	if (
		unit.nav_agent.is_navigation_finished() or
		current_distance > _path_update_threshold or
		unit.nav_agent.distance_to_target() > current_distance * 1.2
	):
		# 设置新目标位置
		unit.nav_agent.target_position = desired_pos
		# 强制刷新导航路径（Godot 4.1+导航系统特殊需求）
		NavigationServer2D.agent_set_position(
			unit.nav_agent.get_rid(),
			unit.global_position
		)
##endregion
func _apply_avoidance(unit: Unit, base_dir: Vector2, current_velocity: Vector2) -> Vector2:
	# 生成三角形检测区域
	var triangle = _create_detect_shape(base_dir)
	
	# 执行物理检测
	var query = PhysicsShapeQueryParameters2D.new()
	query.shape = triangle
	if unit.is_in_group("ally"):
		query.collision_mask = ally_collision_mask
	if unit.is_in_group("enemy"):
		query.collision_mask = enemy_collision_mask
	query.transform = unit.global_transform # 新增坐标变换设置
	var results = unit.get_world_2d().direct_space_state.intersect_shape(query)
	
	# 简单避让规则
	if results.size() >= 2:
		var left_dir = base_dir.rotated(- PI / 2)
		return left_dir * unit.speed * _avoid_speed_ratio
	
	return current_velocity

func _create_detect_shape(base_dir: Vector2) -> ConvexPolygonShape2D:
	# 仅当方向变化超过5度时更新形状（避免频繁计算）
	if abs(base_dir.angle_to(_last_dir)) > deg_to_rad(5):
		_update_shape_points(base_dir)
		_last_dir = base_dir
	return _cached_shape

func _update_shape_points(base_dir: Vector2):
	var forward = base_dir * _avoid_distance
	_cached_shape.points = PackedVector2Array([
		Vector2.ZERO,
		forward + base_dir.rotated(_avoid_angle / 2) * _avoid_distance,
		forward + base_dir.rotated(- _avoid_angle / 2) * _avoid_distance
	])
##endregion

##region 辅助方法
func _calculate_base_velocity(unit: Unit, base_dir: Vector2) -> Vector2:
	var current_distance = unit.nav_agent.distance_to_target()
	var speed_factor = 1.0 - smoothstep(20.0, 3.0, current_distance)
	return base_dir * unit.speed * clamp(speed_factor, 0.2, 1.0)

func _handle_collision_check_timer(delta: float, unit: Unit):
	_collision_check_timer += delta
	if _collision_check_timer > 1.0:
		var area = unit.target_enter_area
		var bodies = area.get_overlapping_bodies()
		for body in bodies:
			area.body_entered.emit(body)

func _exit() -> void:
	var unit = agent as Unit
	unit.nav_agent.avoidance_priority = 1
	unit.nav_agent.velocity = Vector2.ZERO
